package org.jeecg.common.util;

import com.alibaba.fastjson.JSONObject;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

/**
 * 调用 Restful 接口 Util
 *
 * @author sunjianlei
 */
@Slf4j
public class RestUtil {

  private static String domain = null;

  public static String getDomain() {
    if (domain == null) {
      domain = SpringContextUtils.getDomain();
    }
    return domain;
  }

  public static String path = null;

  public static String getPath() {
    if (path == null) {
      path =
          SpringContextUtils.getApplicationContext()
              .getEnvironment()
              .getProperty("server.servlet.context-path");
    }
    return oConvertUtils.getString(path);
  }

  public static String getBaseUrl() {
    String basepath = getDomain() + getPath();
    log.info(" RestUtil.getBaseUrl: " + basepath);
    return basepath;
  }

  /** RestAPI 调用器 */
  private static final RestTemplate RT;

  static {
    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setConnectTimeout(3000);
    requestFactory.setReadTimeout(3000);
    RT = new RestTemplate(requestFactory);
    // 解决乱码问题
    RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
  }

  public static RestTemplate getRestTemplate() {
    return RT;
  }

  /** 发送 get 请求 */
  public static JSONObject get(String url) {
    return getNative(url, null, null).getBody();
  }

  /** 发送 get 请求 */
  public static JSONObject get(String url, JSONObject variables) {
    return getNative(url, variables, null).getBody();
  }

  /** 发送 get 请求 */
  public static JSONObject get(String url, JSONObject variables, JSONObject params) {
    return getNative(url, variables, params).getBody();
  }

  /** 发送 get 请求，返回原生 ResponseEntity 对象 */
  public static ResponseEntity<JSONObject> getNative(
      String url, JSONObject variables, JSONObject params) {
    return request(url, HttpMethod.GET, variables, params);
  }

  /** 发送 Post 请求 */
  public static JSONObject post(String url) {
    return postNative(url, null, null).getBody();
  }

  /** 发送 Post 请求 */
  public static JSONObject post(String url, JSONObject params) {
    return postNative(url, null, params).getBody();
  }

  /** 发送 Post 请求 */
  public static JSONObject post(String url, JSONObject variables, JSONObject params) {
    return postNative(url, variables, params).getBody();
  }

  /** 发送 POST 请求，返回原生 ResponseEntity 对象 */
  public static ResponseEntity<JSONObject> postNative(
      String url, JSONObject variables, JSONObject params) {
    return request(url, HttpMethod.POST, variables, params);
  }

  /** 发送 put 请求 */
  public static JSONObject put(String url) {
    return putNative(url, null, null).getBody();
  }

  /** 发送 put 请求 */
  public static JSONObject put(String url, JSONObject params) {
    return putNative(url, null, params).getBody();
  }

  /** 发送 put 请求 */
  public static JSONObject put(String url, JSONObject variables, JSONObject params) {
    return putNative(url, variables, params).getBody();
  }

  /** 发送 put 请求，返回原生 ResponseEntity 对象 */
  public static ResponseEntity<JSONObject> putNative(
      String url, JSONObject variables, JSONObject params) {
    return request(url, HttpMethod.PUT, variables, params);
  }

  /** 发送 delete 请求 */
  public static JSONObject delete(String url) {
    return deleteNative(url, null, null).getBody();
  }

  /** 发送 delete 请求 */
  public static JSONObject delete(String url, JSONObject variables, JSONObject params) {
    return deleteNative(url, variables, params).getBody();
  }

  /** 发送 delete 请求，返回原生 ResponseEntity 对象 */
  public static ResponseEntity<JSONObject> deleteNative(
      String url, JSONObject variables, JSONObject params) {
    return request(url, HttpMethod.DELETE, null, variables, params, JSONObject.class);
  }

  /** 发送请求 */
  public static ResponseEntity<JSONObject> request(
      String url, HttpMethod method, JSONObject variables, JSONObject params) {
    return request(url, method, getHeaderApplicationJson(), variables, params, JSONObject.class);
  }

  /**
   * 发送请求
   *
   * @param url 请求地址
   * @param method 请求方式
   * @param headers 请求头 可空
   * @param variables 请求url参数 可空
   * @param params 请求body参数 可空
   * @param responseType 返回类型
   * @return ResponseEntity<responseType>
   */
  public static <T> ResponseEntity<T> request(
      String url,
      HttpMethod method,
      HttpHeaders headers,
      JSONObject variables,
      Object params,
      Class<T> responseType) {
    log.info(" RestUtil  --- request ---  url = " + url);
    if (StringUtils.isEmpty(url)) {
      throw new RuntimeException("url 不能为空");
    }
    if (method == null) {
      throw new RuntimeException("method 不能为空");
    }
    if (headers == null) {
      headers = new HttpHeaders();
    }
    // 请求体
    String body = "";
    if (params != null) {
      if (params instanceof JSONObject) {
        body = ((JSONObject) params).toJSONString();

      } else {
        body = params.toString();
      }
    }
    // 拼接 url 参数
    if (variables != null) {
      url += ("?" + asUrlVariables(variables));
    }
    // 发送请求
    HttpEntity<String> request = new HttpEntity<>(body, headers);
    return RT.exchange(url, method, request, responseType);
  }

  /** 获取JSON请求头 */
  public static HttpHeaders getHeaderApplicationJson() {
    return getHeader(MediaType.APPLICATION_JSON_UTF8_VALUE);
  }

  /** 获取请求头 */
  public static HttpHeaders getHeader(String mediaType) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.parseMediaType(mediaType));
    headers.add("Accept", mediaType);
    return headers;
  }

  /** 将 JSONObject 转为 a=1&b=2&c=3...&n=n 的形式 */
  public static String asUrlVariables(JSONObject variables) {
    Map<String, Object> source = variables.getInnerMap();
    Iterator<String> it = source.keySet().iterator();
    StringBuilder urlVariables = new StringBuilder();
    while (it.hasNext()) {
      String key = it.next();
      String value = "";
      Object object = source.get(key);
      if (object != null) {
        if (!StringUtils.isEmpty(object.toString())) {
          value = object.toString();
        }
      }
      urlVariables.append("&").append(key).append("=").append(value);
    }
    // 去掉第一个&
    return urlVariables.substring(1);
  }
}
